package com.firesrc.mail.send;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedQueue;

import jodd.mail.Email;
import jodd.mail.SendMailSession;
import jodd.mail.SimpleAuthenticator;
import jodd.mail.SmtpServer;
import jodd.mail.SmtpSslServer;
import jodd.util.collection.SimpleQueue;
import lombok.Data;

import com.firesrc.bean.ExceptionLog;
import com.firesrc.bean.Record;

@Data
public class MailSender {
  protected String userName;
  protected String password;
  protected SendMailSession session;
  protected int maxDayCount = 0;
  protected int alreadyDayCount = 0;
  protected int maxOnceCount = 0;
  protected int alreadysendOnceCount = 0;
  private String mail;
  private boolean isSsl;
  private String hostName;
  private String kind;

  private List<MailObserver> observerList = new ArrayList<MailObserver>();

  public MailSender(String userName, String password) {
    this.userName = userName;
    this.password = password;
    observerList.add(new LogMailObserver(this));
  }

  protected SmtpServer getSmtpServer() {
    if (!isSsl) {
      new SmtpServer(hostName, new SimpleAuthenticator(userName, password));
    }
    return new SmtpSslServer(hostName, new SimpleAuthenticator(userName, password));
  };

  public boolean sendSingleMailFromRecord(Record record) {
    initSession();

    if (alreadyDayCount >= maxDayCount) {
      if (session != null) {
        session.close();
        session = null;
      }
      System.err.println("MailSender.batchSendMail() 邮箱:" + getMail() + "已经超过最大值 " + getMaxDayCount() + "  不能继续发送");
      return false;
    }
    if (singleSendMail(record)) {
      alreadyDayCount++;
      System.out.println("发送成功 alreadyDayCount+1 =" + alreadyDayCount);
      return true;
    }
    return false;
  }

  private void initSession() {
    if (session == null) {
      session = getSmtpServer().createSession();
      session.open();
    }
  }

  public void closeSession() {
    try {
      session.close();
    } catch (Exception e) {
      System.out.println("MailSender.closeSession() 关闭session出错" + getMail() + "错误信息:" + e.getMessage());
    }
  }

  public MailSender openSession() {
    if (alreadyDayCount >= maxDayCount) {
      return null;
    }
    session = getSmtpServer().createSession();
    try {
      session.open();
    } catch (Exception e) {
      handleOpenSessionException(e);
      System.err.println("MailSender.openSession() 打开邮箱<" + getMail() + "出错,错误信息是:" + e.getMessage());
      return null;
    }
    return this;
  }

  private void handleOpenSessionException(Exception e) {
    ExceptionLog log = new ExceptionLog();
    log.setId(UUID.randomUUID().toString());
    log.setClassName(this.getClass().getSimpleName());
    log.setMethodName("openSession");
    log.setCustomMessage("打开邮箱<" + getMail() + "出错");
    log.setCauseMessage(e.getCause().getMessage());
    log.setMessage(e.getMessage());
    log.setKind("打开邮箱");
    log.setState("0");
    for (MailObserver mailObserver : observerList) {
      mailObserver.handleOpenSessionFail(log);
    }
  }

  public boolean singleSendMail(Record record) {
    String mailContent = MailHelper.getMailText(record);
    try {
      Email email = Email.create().from(getMail()).to(record.getMail()).subject(MailHelper.getSubject(record)).addText(mailContent);
      session.sendMail(email);
      System.out.println("SuperMailSender.singleSendMail()-->用:<" + getMail() + ">发送邮件---->" + record.getMail() + "成功");
      return true;
    } catch (Exception e) {
      handleSendMailException(record, e);
      System.err.println("发送邮件失败:MailSender.singleSendMail()==> " + getMail() + "---->" + record.getMail() + "");
      System.err.println("发送邮件失败:错误信息是:" + e.getMessage());
      return false;
    }
  }

  private void handleSendMailException(Record record, Exception e) {
    ExceptionLog log = new ExceptionLog();
    log.setId(UUID.randomUUID().toString());
    log.setClassName(this.getClass().getSimpleName());
    log.setMethodName("singleSendMail");
    log.setCustomMessage("用<" + getMail() + "> 发送邮件到<" + record.getMail() + "出错");
    log.setCauseMessage(e.getCause().getMessage());
    log.setMessage(e.getMessage());
    log.setKind("发送邮件");
    log.setState("0");
    for (MailObserver mailObserver : observerList) {
      mailObserver.handleOpenSessionFail(log);
      mailObserver.fail(record, e);
    }
  }

  public String SingleSendMail(String mail) {
    try {
      SendMailSession createSession = getSmtpServer().createSession();
      createSession.open();
      Email email = Email.create().from(getMail()).to(mail).subject("测试主题").addText("测试邮件的内容");
      createSession.sendMail(email);
      createSession.close();
      return "1";
    } catch (Exception e) {
      return e.getMessage();
    }

  }

  public void batchSendMail(SimpleQueue<Record> queue) {
    initSession();
    for (int i = 0; i < getMaxOnceCount(); i++) {
      Record record = queue.get();
      if (record != null) {
        try {
          Thread.sleep(200);
        } catch (InterruptedException e) {
          System.out.println("MailSender.batchSendMail() InterruptedException");
        }
        boolean isSendSuccess = singleSendMail(record);
        if (isSendSuccess) {
          for (MailObserver mailObserver : observerList) {
            mailObserver.success(record);
          }
        }
      }
    }
    closeSession();
  }

  public void batchSendMail(ConcurrentLinkedQueue<Record> queue) {
    initSession();
    int maxOnceCount2 = getMaxOnceCount();
    if (maxOnceCount2 <= 0) {
      System.err.println("邮箱" + getMail() + "每次设定的发送值小于等于零,系统里面修改为大于1,否则不能发送");
      return;
    }
    for (int i = 0; i < maxOnceCount2; i++) {
      Record record = queue.poll();
      if (record != null) {
        try {
          Thread.currentThread().sleep(2 * 60 * 1000);
        } catch (InterruptedException e) {
          System.out.println("MailSender.batchSendMail() InterruptedException");
        }
        boolean isSendSuccess = sendSingleMailFromRecord(record);
        if (isSendSuccess) {
          for (MailObserver mailObserver : observerList) {
            mailObserver.success(record);
          }
        }
      }
    }
    closeSession();
  }
}